<!--
 * @Author: xujianhua
 * @Date: 2021-04-01 17:06:04
 * @LastEditTime: 2021-04-06 09:13:11
 * @Description: file content
 * @FilePath: \TaskErrorManage\src\views\layoutpages\leisure\Game.vue
-->
<template>
  <div id="ve_puzzle">
    <div
      class="ve_artwork"
      :style="{
        backgroundImage: show_img || success ? `url(${img})` : 'none',
      }"
    >
      <div
        v-for="i in 16"
        :key="i"
        :class="[
          've_item_box',
          `pic${i}`,
          `img${arr[i - 1]}`,
          show_img || success ? 've_show_img' : '',
          success && i == 16 ? 've_finish' : '',
        ]"
        :style="{
          backgroundImage:
            i == 16 ? (success ? `url(${img})` : 'none') : `url(${img})`,
        }"
        :ref="
          (el) => {
            if (el) divs[i - 1] = el;
          }
        "
        @click.self.stop="move_img(i - 1, $event)"
      />
    </div>
    <div class="ve_button">
      <div class="ve_game_button">
        <el-row :gutter="10">
          <el-col :span="12" :offset="0">
            <el-button type="primary" @click="get_nums()" style="width: 100%"
              >重新开始</el-button
            >
          </el-col>
          <el-col :span="12" :offset="0">
            <el-button
              style="width: 100%"
              :type="show_img ? 'success' : 'info'"
              @click="see_img()"
              :disabled="success"
              >{{ txt }}</el-button
            >
          </el-col>
        </el-row>
      </div>
      <div class="ve_upload">
        <el-upload
          style="width: 100%"
          action=""
          accept="image/png, image/jpeg"
          ref="upload"
          :on-change="onChange"
          :auto-upload="false"
          :show-file-list="false"
        >
          <el-button style="width: 100%" type="danger">用我的萌照</el-button>
        </el-upload>
      </div>
    </div>
  </div>
</template>

<script>
import { ref, onBeforeUpdate } from "vue";
let url = require("../../../assets/logo.png");
export default {
  data: () => ({
    description: "拼图小游戏",
  }),
  setup() {
    const img = ref(url);
    const show_img = ref(false);
    const txt = ref("查看原图");
    const divs = ref([]);
    const arr = ref([]);
    const success = ref(false); //游戏状态
    /**
     * @description:换图片
     * @param {*}
     * @return {*}
     */
    const onChange = (file) => {
      img.value = URL.createObjectURL(file.raw);
      get_nums();
      // console.log(URL.createObjectURL(file.raw));
    };

    /**
     * @description: 查看原图
     * @param {*}
     * @return {*}
     */
    const see_img = () => {
      show_img.value = !show_img.value;
      txt.value = show_img.value ? "继续游戏" : "查看原图";
    };
    /**
     * @description:初始化,生成1-16的16个随机排列的数字
     * @param {*}
     * @return {*}
     */
    const get_nums = () => {
      txt.value = "查看原图";
      show_img.value = false;
      success.value = false;
      arr.value.length = 0;
      for (let i = 1; i < 16; i++) {
        arr.value.push(i);
      }
      // eslint-disable-next-line no-constant-condition
      while (true) {
        arr.value.sort(() => 0.5 - Math.random());
        if (check_nums(arr.value)) {
          break;
        }
      }
      arr.value.push(16);
    };
    /**
     * @description: 检查打乱后的数组是否合理
     * @param {*}
     * @return {*}
     */
    const check_nums = (arr) => {
      let count = 0;
      for (let i = 0; i < 15; i++) {
        for (let j = i + 1; j < 15; j++) {
          if (arr[j] < arr[i]) {
            count++;
          }
        }
      }
      return count % 2 === 0;
    };
    /**
     * @description:检查是否拼图成功
     * @param {*}
     * @return {*}
     */
    const check_finish = () => {
      let bool = arr.value.every((item, i) => {
        return item == i + 1;
      });
      bool && (success.value = true);
    };
    /**
     * @description:图片点击事件,移动图片
     * @param {*}
     * @return {*}
     */
    const move_img = (i, e) => {
      let top = e.target.offsetTop;
      let left = e.target.offsetLeft;
      let top_16 = divs.value[15].offsetTop;
      let left_16 = divs.value[15].offsetLeft;
      let x = Math.abs(left - left_16);
      let y = Math.abs(top - top_16);
      if ((x == 100 && top == top_16) || (y == 100 && left == left_16)) {
        let a = arr.value[15];
        arr.value[15] = arr.value[i];
        arr.value[i] = a;
        check_finish();
      }
    };
    get_nums();
    // 确保在每次更新之前重置ref
    onBeforeUpdate(() => {
      divs.value = [];
    });
    return {
      img,
      txt,
      arr,
      divs,
      move_img,
      get_nums,
      see_img,
      success,
      show_img,
      onChange,
    };
  },
};
</script>

<style lang="scss" scoped>
#ve_puzzle {
  margin-top: 10px;
  .ve_artwork {
    margin: 0 auto;
    position: relative;
    width: 399px;
    height: 399px;
    background-size: 399px;
    box-shadow: 1px 1px 10px rgb(168, 168, 168),
      -1px -1px 10px rgb(168, 168, 168);

    .ve_item_box {
      opacity: 1;
      cursor: pointer;
      position: absolute;
      z-index: 2;
      width: 99px;
      height: 99px;
      transition: all 0.2s;
      background-repeat: no-repeat;
      background-size: 399px;
      &.ve_show_img {
        opacity: 0;
      }
    }
    @for $i from 1 through 4 {
      @for $j from ($i - 1) * 4 + 1 through ($i - 1) * 4 + 4 {
        .img#{$j} {
          top: #{($i - 1) * 100}px;
        }
        .pic#{$j} {
          background-position-y: -#{($i - 1) * 100}px;
        }
      }
      @for $k from $i through $i + 3 {
        .img#{ ($k - $i) * 4 + $i} {
          left: #{($i - 1) * 100}px;
        }
        .pic#{ ($k - $i) * 4 + $i} {
          background-position-x: -#{($i - 1) * 100}px;
        }
      }
    }
    .pic16 {
      transition: none;
      box-shadow: inset 1px 1px 10px rgb(168, 168, 168),
        inset -1px -1px 10px rgb(168, 168, 168);
      z-index: 1;
      &.ve_finish {
        box-shadow: none;
      }
    }
  }
  .ve_button {
    width: 409px;
    margin: 0 auto;
    .ve_game_button {
      margin: 10px 0;
    }
  }
  & :deep(.el-upload--text) {
    width: 100%;
  }
}
</style>
